﻿/** PROGRAM CLASS
 * Author: Preeti Francis
 * User ID : pxfranci@scotty.cs.wichita.edu
 * WSU ID: S578F746
 * Course: CS771 
 * Sem: S2014
 * 
 * Description of Class : It contains the Main() method and contains the starting point of the program
 * This class interacts with the user. It asks the user to provide the dimensions of the chessboard and 
 * the initial configuration of the chess board i.e., it asks the user to provide a position for a queen
 * for every column. On getting the initial configuration, it creates an instance of the constraint satisfacton
 * problem and provides the initial values. It passes the CSP problem to the min conflicts algorithm i.e., it 
 * functions as an entry point for the min conflict algorithm. 
 * **/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NQueenPuzzle
{
    class Program
    {
        //Dimensions of the chessboard 
        public int N { get; set; }

        static void Main(string[] args)
        {
            StartNewProblem();
            
        }

        //Starts a new problem
        private static void StartNewProblem()
        {
            int n = GetSizeOfChessboard();

            int[,] chessBoard = new int[n, n];
            
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    chessBoard[i, j] = 0;
                }
            }
            //Iterate through each column and get the position for queen in that column
            for (int i = 0; i < n; i++)
            {
                int rowQ = GetQueenPosition(n, i);

                chessBoard[rowQ - 1, i] = 1;
            }

            Console.WriteLine("\r\nThe initial configuration entered is as follows: \r\n");

            ShowOutput(n, chessBoard);

            var solution = RunMinConflict(n, chessBoard);

            Console.WriteLine();

            if (solution != null)
            {
                Console.WriteLine("\r\nSolution: \r\n");
                ShowOutput(n, solution);
            }
            else
            {
                Console.WriteLine("The solution is not achievable in 1000 steps");
            }

            Console.WriteLine("\r\nDo you want to continue with a new game?\r\nPress 'y' to continue or any key to exit.");

            string response = Console.ReadLine();

            if (response == "y" || response == "Y")
            {
                StartNewProblem();
            }
        }

        //Gets valid positions of the queens in each column from the user
        private static int GetQueenPosition(int n, int i)
        {
            string message = string.Format("Enter the row position (between 1 to {0}) for the Queen in column ", n.ToString());

            Console.WriteLine(message + (i + 1));

            int rowQ;

            bool isRowQ = Int32.TryParse(Console.ReadLine(), out rowQ);

            if (!isRowQ || (rowQ<1 ||rowQ>n))
            {
                Console.WriteLine( string.Format("The row number should be an integer between 1 and {0}. Please try again.", n));
                            
                return GetQueenPosition(n, i);
            }

            return rowQ;
        }

        //Gets a valid dimension for the chessboard from the user
        private static int GetSizeOfChessboard()
        {
            Console.WriteLine("Enter the value of N (atleast 4)");

            string size = Console.ReadLine();

            int n;

            bool isInt = Int32.TryParse(size, out n);

            if (!isInt || (n<4))
            {
                Console.WriteLine("N should be an integer value that is atleast 4.Please try again.");

                return GetSizeOfChessboard();
            }

            Console.WriteLine(n);

            return n;
        }

        //Starting point for the min conflict algorithm : passes the initial values 
        private static int[,] RunMinConflict(int n, int[,] chessBoard)
        {
                ConstraintSatisfactionProblem csp = new ConstraintSatisfactionProblem(n, chessBoard);

                MinConflict minConflict = new MinConflict();

                var solution = minConflict.GetSolution(csp, 1000);

                return solution;   
        }

        //Displays the board on console
        private static void ShowOutput(int n, int[,] chessBoard)
        {
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    Console.Write(" " + chessBoard[i, j]);
                }
                Console.WriteLine();
            }
        }
    }
}
